package cn.xhz.gdal.config;

import cn.xhz.gdal.config.driver.DriverConfig;
import cn.xhz.gdal.config.driver.impl.EnvironmentVariablesMethodImpl;
import cn.xhz.gdal.constant.GDALGlobalConstanst;
import cn.xhz.gdal.enums.GDALExceptionEnum;
import cn.xhz.gdal.enums.GDALTypeEnum;
import cn.xhz.gdal.exception.GDALException;
import cn.xhz.gdal.model.GDAL;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;

/**
 * gdal 全局环境配置类
 *
 * @author life-oss
 * @since 2022/12/13
 */
public class ConfigUtil {
    private static final DriverConfig driverConfig;
    static {
        driverConfig=new EnvironmentVariablesMethodImpl();
    }
    /**
     * 初始化GDAL环境
     * @since 1.0
     */
    public static void initContext(){
        driverConfig.start();
        /*
        以下情况适合java开发环境，若是其余环境请另外配置
         */
        // 为了支持中文路径
        gdal.SetConfigOption(GDALGlobalConstanst.GDAL_FILENAME_IS_UTF8, "YES");
        // 为了使属性表字段支持中文,但是仍然会出现中文的情况
        gdal.SetConfigOption(GDALGlobalConstanst.SHAPE_ENCODING, "");
    }

    /**
     * 帮助在程序调用之前初始化驱动，若是存在，便不做什么
     * 若是初始化之后还存在问题，就会报错
     * @param driverNames 驱动类型
     */
    public static void initContext(GDALTypeEnum... driverNames){
        if (!checkGDALContext(driverNames)) {
            initContext();
            if (!checkGDALContext(driverNames)) {
                throw new GDALException(GDALExceptionEnum.GDAL_CONTEXT);
            }
        }
    }
    /**
     * 检查驱动
     * @param driverNames 驱动类型
     * @return 结果
     * @since 1.0
     */
    public static boolean checkGDALContext(GDALTypeEnum... driverNames){
        if (driverNames==null) {
            return true;
        }
        for (GDALTypeEnum gdalTypeEnum : driverNames) {
            Driver oDriver = ogr.GetDriverByName(gdalTypeEnum.getType());
            if (oDriver == null) {
                return false;
            }
        }
        return true;
    }


    /**
     * 关闭图层对象
     * 此方法并未封装什么，只是习惯性调用
     * @param layer 图层
     */
    public static void stopLayer(Layer layer){
        if (layer!=null){
            layer.delete();
        }
    }

    /**
     * 写入图层对象
     * 在写入对象时请调用这个方法，否则图层对象为空的话会发生虚拟机崩溃
     * 在这里用了报错处理
     * @param layer 图层
     */
    public static void writeLayer(Layer layer){
        if (layer!=null){
            layer.SyncToDisk();
        }else {
            throw new GDALException(GDALExceptionEnum.OBJECT);
        }
    }

    /**
     * 关闭图层对象
     * 此方法并未封装什么，只是习惯性调用
     * @param dataSource 数据源
     */
    public static void stopDataSource(DataSource dataSource){
        if (dataSource!=null){
            dataSource.delete();
        }
    }

    /**
     * 与图层对象相同原理
     * 这里使用报错处理
     * @param dataSource 数据源
     */
    public static void writeDataSource(DataSource dataSource){
        if (dataSource!=null){
            dataSource.SyncToDisk();
        }else {
            throw new GDALException(GDALExceptionEnum.OBJECT);
        }
    }

    /**
     * 关闭上下文
     * 该方法会把自身的驱动卸载
     */
    public static void stopContext(){
        driverConfig.stop();
    }

    /**
     * 关闭操作对象
     * @param gdal
     */
    public static void stopContext(GDAL gdal,boolean isCloseDriver){
        stopLayer(gdal.getLayer());
        stopDataSource(gdal.getDataSource());
        if (isCloseDriver){
            stopContext();
        }
    }

    /**
     * 依次关闭gdal环境
     * @param gdal
     */
    public static void stopContext(GDAL gdal){
        stopContext(gdal,false);
    }

    /**
     * 提交事务
     * @param gdal 需要图层对象和数据源对象
     */
    public static void commit(GDAL gdal){
        writeLayer(gdal.getLayer());
        writeDataSource(gdal.getDataSource());
    }
}
